package com.af.robot.controller;

import com.af.robot.result.ResultEnum;
import com.af.robot.scanner.Catalogue;
import com.af.robot.util.CmdRun;
import com.af.robot.util.imp.NginxManager;
import com.af.robot.util.imp.TomcatManager;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.Collator;
import java.util.Locale;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;

@RestController
@RequestMapping("/service")
public class ServiceController {

    @Autowired
    private Catalogue catalogue;

    @Autowired
    private com.af.robot.config.ConfigThermalData configThermalData;

    @Autowired
    private TomcatManager tomcatManager;

    @Autowired
    private NginxManager nginxManager;

    /**
     * 获取所有配置服务的列表和存活状态
     * @return 返回所有配置的服务名称 列表和状态存活状态
     */
    @GetMapping("/getDirConfig")
    public JSONObject getList(){
        JSONObject dirConfig = configThermalData.getDirConfig();
        JSONObject res = ResultEnum.OK.getResult();
        CopyOnWriteArrayList<JSONObject> tomcat = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<JSONObject> nginx = new CopyOnWriteArrayList<>();
        CopyOnWriteArrayList<JSONObject> other = new CopyOnWriteArrayList<>();
        //利用减法计数器，控制多个服务同时测试存活状态，并等待所有测试完成后，再填充数据执行
        CountDownLatch countTomcat = new CountDownLatch(0);
        CountDownLatch countNginx = new CountDownLatch(0);
        //如果存在Tomcat的配置，则执行
        if (dirConfig.containsKey("tomcat")){
            JSONArray tomcats = dirConfig.getJSONArray("tomcat");
            countTomcat = new CountDownLatch(tomcats.size());
            for (int i = 0; i < tomcats.size(); i++) {
                int finalI = i;
                CopyOnWriteArrayList<JSONObject> finalTomcat = tomcat;
                CountDownLatch finalCountTomcat = countTomcat;
                new Thread(()->{
                    JSONObject one = new JSONObject();
                    JSONObject tom = tomcats.getJSONObject(finalI);
                    one.put("name",tom.getString("af_name"));
                    one.put("isAlive", tomcatManager.isLive("http://127.0.0.1:" + tom.get("af_port").toString() + "/robotMonitor/live.html") || CmdRun.isListen(tom.get("af_port").toString()));
                    one.put("type","tomcat");
                    finalTomcat.add(one);
                    finalCountTomcat.countDown();
                }).start();
            }
        }
        //如果存在Nginx的配置，则执行
        if (dirConfig.containsKey("nginx")){
            JSONArray nginxs = dirConfig.getJSONArray("nginx");
            countNginx = new CountDownLatch(nginxs.size());
            for (int i = 0; i < nginxs.size(); i++) {
                int finalI = i;
                CountDownLatch finalCountNginx = countNginx;
                CopyOnWriteArrayList<JSONObject> finalNginx = nginx;
                new Thread(()->{
                    JSONObject one = new JSONObject();
                    JSONObject ngi = nginxs.getJSONObject(finalI);
                    one.put("name",ngi.getString("af_name"));
                    one.put("isAlive",nginxManager.isLive("http://127.0.0.1:"+ ngi.get("af_port").toString()+"/robotMonitor/live.html") || CmdRun.isListen(ngi.get("af_port").toString()));
                    one.put("type","nginx");
                    finalNginx.add(one);
                    finalCountNginx.countDown();
                }).start();
            }
        }
        if (dirConfig.containsKey("other")){
            JSONArray others = dirConfig.getJSONArray("other");
            for (int i = 0; i < others.size(); i++) {
                JSONObject one = new JSONObject();
                JSONObject oneOther = others.getJSONObject(i);
                one.put("name",oneOther.getString("af_name"));
                one.put("type","other");
                other.add(one);
            }
        }
        try {
            countTomcat.await();
            countNginx.await();
        } catch (InterruptedException e) {
            tomcat = new CopyOnWriteArrayList<JSONObject>();
            nginx = new CopyOnWriteArrayList<JSONObject>();
        }
        if (tomcat.size() > 1 ){
            tomcat.sort((o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1.getString("name"), o2.getString("name")));
        }
        if (nginx.size() > 1 ){
            nginx.sort((o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1.getString("name"), o2.getString("name")));
        }
        if (other.size() > 1 ){
            other.sort((o1, o2) -> Collator.getInstance(Locale.CHINESE).compare(o1.getString("name"), o2.getString("name")));
        }
        res.put("tomcat",tomcat);
        res.put("nginx",nginx);
        res.put("other",other);
        return res;
    }

    /**
     * 启动对应名称服务
     * @param type 服务类型 tomcat||nginx
     * @param name 服务名称 详见 dirConfig -> af_name
     * @return 返回执行结果
     */
    @PostMapping("/startService/{type}/{name}")
    public JSONObject startService(@PathVariable String type, @PathVariable String name){
        if (!("tomcat".equals(type) || "nginx".equals(type))){
            return ResultEnum.PARAMETER_ERROR.getResult();
        }
        boolean success = false;
        JSONArray list = configThermalData.getDirConfig().getJSONArray(type);
        for (int i = 0; i < list.size(); i++) {
            JSONObject one = list.getJSONObject(i);
            if (name.equals(one.getString("af_name"))){
                if ("tomcat".equals(type)) {
                    tomcatManager.start(one.getString("af_path") + "\\bin");
                } else {
                    nginxManager.start(one.getString("af_path") + "<" + one.getString("af_file"));
                }
                success = true;
                break;
            }
        }
        return success ? ResultEnum.OK.getResult() : ResultEnum.SERVICE_NAME_ERROR.getResult();
    }

    /**
     * 关停启动服务
     * @param type 服务类型 tomcat||nginx
     * @param name 服务名称 详见 dirConfig -> af_name
     * @return 返回执行结果
     */
    @PostMapping("/stopService/{type}/{name}")
    public JSONObject stopService(@PathVariable String type,@PathVariable String name){
        if (!("tomcat".equals(type) || "nginx".equals(type))){
            return ResultEnum.PARAMETER_ERROR.getResult();
        }
        boolean success = false;
        JSONArray list = configThermalData.getDirConfig().getJSONArray(type);
        for (int i = 0; i < list.size(); i++) {
            JSONObject one = list.getJSONObject(i);
            if (name.equals(one.getString("af_name"))){
                if ("tomcat".equals(type)) {
                    tomcatManager.stop(one.get("af_port").toString());
                } else {
                    nginxManager.stop(one.getString("af_path") + "<" + one.getString("af_file"));
                }
                success = true;
                break;
            }
        }
        return success ? ResultEnum.OK.getResult() : ResultEnum.SERVICE_NAME_ERROR.getResult();
    }

    /**
     * 获取机器人部署环境信息
     * @return
     */
    @GetMapping("/sysInfo")
    public JSONObject getSystemInfo(){
        return configThermalData.getSystemEnvironment();
    }


    /**
     * 传入文件夹路径 打开文件夹
     * @return
     */
    @PostMapping("/openDir/{type}/{name}")
    public JSONObject openDIR(@PathVariable String type,@PathVariable String name){
        boolean success = false;
        //寻找对应的配置
        JSONArray list = configThermalData.getDirConfig().getJSONArray(type);
        for (int i = 0; i < list.size(); i++) {
            JSONObject one = list.getJSONObject(i);
            if (name.equals(one.getString("af_name"))){
                try {
                    Desktop.getDesktop().open(new File(one.getString("af_path")));
                    success = true;
                    break;
                } catch (Exception e) {
                    return ResultEnum.JURISDICTION_ERROR.getResult();
                }
            }
        }
        return success ? ResultEnum.OK.getResult() : ResultEnum.SERVICE_NAME_ERROR.getResult();
    }
}
